package com.hitqz.robot.biz.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import com.hitqz.robot.api.business.enums.MapTypeEnum;
import com.hitqz.robot.api.business.model.param.robotMap.QueryMapParams;
import com.hitqz.robot.api.business.model.vo.roboMap.RobotMapVo;
import com.hitqz.robot.api.common.dto.file.UploadFileVo;
import com.hitqz.robot.api.common.dto.map.AddRobotMap;
import com.hitqz.robot.api.common.dto.map.UpdateRobotMapPng;
import com.hitqz.robot.api.common.entity.Robot;
import com.hitqz.robot.api.common.entity.RobotMap;
import com.hitqz.robot.api.common.entity.RobotMapPos;
import com.hitqz.robot.biz.core.FileProperties;
import com.hitqz.robot.biz.service.RobotMapPosService;
import com.hitqz.robot.biz.service.RobotMapService;
import com.hitqz.robot.biz.service.RobotService;
import com.hitqz.robot.common.core.util.R;
import com.hitqz.robot.driver.parent.RobotDriverService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author xupkun
 * @date 2024/5/21
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/robotMap")
@Tag(name = "地图管理")
public class RobotMapController {

    private final RobotMapService robotMapService;

    private final RobotMapPosService robotMapPosService;

    private final FileProperties fileProperties;

    private final RobotDriverService robotDriverService;

    private final RobotService robotService;

    @GetMapping(value = "{mapCode}")
    @Operation(summary = "获取地图详细信息")
    public R<RobotMap> getMapDetail(@PathVariable String mapCode) {
        return R.ok(robotMapService.findByMapCode(mapCode));
    }

    @PostMapping("/page")
    @Operation(summary = "分页查询地图数据")
    public R<Page<RobotMapVo>> page(@RequestBody QueryMapParams queryMapParams) {
        Page page = new Page<>(queryMapParams.getCurrent(),queryMapParams.getSize());
        Page<RobotMap> data = robotMapService.page( page,
                Wrappers.<RobotMap>lambdaQuery()
                        .eq(queryMapParams.getType()!=null,RobotMap::getType, queryMapParams.getType())
                        .like(StrUtil.isNotBlank(queryMapParams.getMapName()), RobotMap::getMapName,
                                queryMapParams.getMapName()));
        Page<RobotMapVo> voPage = new Page<>();
        BeanUtil.copyProperties(data, voPage, false);

        List<RobotMapVo> vos = Lists.newArrayList();

        for (RobotMap robotMap: data.getRecords()) {
            RobotMapVo vo = new RobotMapVo();
            BeanUtil.copyProperties(robotMap, vo, false);
            vo.setType(String.valueOf(vo.getType()));
            vos.add(vo);
        }
        voPage.setRecords(vos);
        return R.ok(voPage);
    }

    @PostMapping
    @Operation(summary = "添加地图")
    public R save(@RequestBody AddRobotMap addRobotMap) {
        RobotMap robotMap = new RobotMap();
        BeanUtil.copyProperties(addRobotMap, robotMap, false);
        if (Objects.equal(addRobotMap.getType(), Integer.parseInt(MapTypeEnum.MAP_TRACK.getCode()))){
            String filePath = "/file/map/"+ robotMap.getMapCode()+".png";
            robotMap.setFilePath(filePath);
        }
        return R.ok(robotMapService.save(robotMap));
    }

    @Operation(summary = "通过id删除地图管理表" , description = "通过id删除地图管理表" )
    @DeleteMapping
    public R removeById(@RequestBody Integer[] ids) {
        return R.ok(robotMapService.removeByIds(Lists.newArrayList(ids)));
    }


    @GetMapping("/generate/trackPng/{mapCode}")
    @Operation(summary = "生成轨道虚拟地图png")
    public R generateMapPng(@PathVariable String mapCode) {
        log.info("生成地图"+mapCode);
        RobotMap map = robotMapService.findByMapCode(mapCode);
        List<RobotMapPos> list = robotMapPosService.list(Wrappers.<RobotMapPos>lambdaQuery().in(RobotMapPos::getMapCode, mapCode));
        if (list.isEmpty()) {
            return R.failed("地图坐标信息为空");
        }
        Map<String, RobotMapPos> posMap = list.stream().collect(Collectors.toMap(RobotMapPos::getCode, pos -> pos));
        // 设定图片的尺寸
        int imgWidth = 1920;  // 图像宽度
        int imgHeight = 1080; // 图像高度
        BufferedImage image = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_ARGB);
        // 创建 Graphics2D 对象来绘制图像
        Graphics2D graphics = image.createGraphics();
        // 背景颜色
        graphics.setColor(Color.GRAY);
        graphics.fillRect(0, 0, imgWidth, imgHeight);
        // 轨道线条的颜色
        graphics.setColor(Color.BLACK);
        // 设置虚线样式
        float[] dashPattern = {2, 2}; // 线段长度和空隙长度
        graphics.setStroke(new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10, dashPattern, 0));
        for (RobotMapPos pos : list) {
            // 根据 pixelX 和 pixelY 绘制坐标点
            int x = pos.getPixelX();
            int y = pos.getPixelY();
            // 绘制圆点或小方块表示坐标点
            graphics.fillOval(x, y, 12, 12);  // 半径5像素的圆点
            // 注释名称
            graphics.drawString(pos.getName(), x , y - 20);  // 坐标点的文字描述
            String preCode = pos.getPreCode();
            if (StrUtil.isBlank(preCode)){
                continue;
            }
            String[] split = preCode.split(",");
            for (String s : split) {
                if (StrUtil.isBlank(s)){
                    continue;
                }
                RobotMapPos prePos = posMap.get(s);
                int preX = prePos.getPixelX();
                int preY = prePos.getPixelY();
                // 绘制虚线
                graphics.drawLine(preX+6, preY+6, x+6, y+6);
            }
        }
        // 释放 Graphics2D 对象
        graphics.dispose();
        try {
            // 将生成的 PNG 图像输出到 HTTP 响应中
            File mapFile = new File(fileProperties.getLocal().getBasePath() + File.separator + map.getFilePath().replaceFirst("/file/",""));
            ImageIO.write(image, "png", mapFile);
        } catch (IOException e) {
            log.error("生成地图图片时发生错误", e);
            return R.failed("生成地图失败");
        }
        return R.ok();
    }


    @PostMapping(value = "updatePng")
    @Operation(summary = "更新png图片")
    public R<RobotMap> updatePng(@RequestBody UpdateRobotMapPng dto) {
        RobotMap robotMap = robotMapService.getById(dto.getId());
        String relativePath = dto.getRelativePath();
        File file = new File(fileProperties.getLocal().getBasePath() + relativePath);
        if (file.exists()) {
            File newFile = new File(fileProperties.getLocal().getBasePath() + relativePath.replaceFirst("upload", "map"));
            FileUtil.move(file, newFile, true);
            try {
                BufferedImage image = ImageIO.read(newFile);
                // 获取图片的宽度和高度
                int width = image.getWidth();
                int height = image.getHeight();
                robotMap.setWidth(width);
                robotMap.setHeight(height);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            robotMap.setFilePath("/file"+relativePath.replaceFirst("upload", "map"));
            robotMapService.updateById(robotMap);
            //同步到driver
            robotMap.setPosList(robotMapPosService.list(Wrappers.<RobotMapPos>lambdaQuery().eq(RobotMapPos::getMapCode, robotMap.getMapCode())));
            robotDriverService.selMap(robotMap);
            //同步到server
            robotMapService.syncMap();
            return R.ok();
        }else {
            return R.failed("文件不存在");
        }
    }


    @PostMapping(value = "updateXmap")
    @Operation(summary = "更新xmap文件")
    public R<RobotMap> updateXmap(@RequestBody UpdateRobotMapPng dto) {
        RobotMap robotMap = robotMapService.getById(dto.getId());
        String relativePath = dto.getRelativePath();
        File file = new File(fileProperties.getLocal().getBasePath() + relativePath);
        if (file.exists()) {
            //解析
            String newFilePath = System.getProperty("user.dir") + File.separator + "xmap" + File.separator + "nav.xmap";
            File newFile =new File(newFilePath);
            FileUtil.move(file,newFile,true);
            List<RobotMap> xMaps = robotDriverService.getMapList();
            if (xMaps==null || xMaps.isEmpty()){
                return R.failed("未解析到地图数据");
            }
            //更新map
            Map<String, RobotMapPos> posMap = robotMapPosService.list(Wrappers.<RobotMapPos>lambdaQuery().eq(RobotMapPos::getMapCode, robotMap.getMapCode()))
                    .stream().collect(Collectors.toMap(RobotMapPos::getCode, f -> f));
            RobotMap xmap = xMaps.get(0);
            BeanUtil.copyProperties(xmap,robotMap, CopyOptions.create().ignoreNullValue());
            robotMapService.updateById(robotMap);
            //同步到server
            robotMapService.syncMap();
            //更新robot
            Robot defaultRobot = robotService.getDefaultRobot();
            defaultRobot.setMapCode(robotMap.getMapCode());
            robotService.updateById(defaultRobot);
            //更新pos
            List<RobotMapPos> xmapPos = robotDriverService.getRobotMapPos(xmap.getMapCode());
            if (xmapPos==null || xmapPos.isEmpty()){
                return R.failed("未解析到点位数据");
            }
            List<RobotMapPos> addRobotMapPosList = new ArrayList<>();
            List<RobotMapPos> updateRobotMapPosList = new ArrayList<>();
            for (RobotMapPos xmapPo : xmapPos) {
                RobotMapPos oldMapPos = posMap.get(xmapPo.getCode());
                if (oldMapPos!=null){
                    oldMapPos.setMapCode(robotMap.getMapCode());
                    oldMapPos.setMapName(robotMap.getMapName());
                    oldMapPos.setCode(xmapPo.getCode());
                    oldMapPos.setPosX(xmapPo.getPosX());
                    oldMapPos.setPosY(xmapPo.getPosY());
                    oldMapPos.setPosZ(xmapPo.getPosZ());
                    oldMapPos.setYaw(xmapPo.getYaw());
                    oldMapPos.setPreCode(xmapPo.getPreCode());
                    updateRobotMapPosList.add(oldMapPos);
                }else {
                    xmapPo.setMapName(robotMap.getMapName());
                    xmapPo.setMapCode(robotMap.getMapCode());
                    addRobotMapPosList.add(xmapPo);
                }
            }
            robotMapPosService.updateBatchById(updateRobotMapPosList);
            robotMapPosService.saveBatch(addRobotMapPosList);
            //同步到driver
            robotMap.setPosList(robotMapPosService.list(Wrappers.<RobotMapPos>lambdaQuery().eq(RobotMapPos::getMapCode, robotMap.getMapCode())));
            robotDriverService.selMap(robotMap);
            //同步到server
            robotMapPosService.syncMapPos();
            return R.ok();
        }else {
            return R.failed("文件不存在");
        }
    }



}
